//
// Created by wxd on 2025/7/14.
//


#pragma once

#include <iostream>

#include <vector>
#include <glm/glm.hpp>
#include <glm/trigonometric.hpp> // 包含三角函数
#include "../wrapper/log/Logger.h"
#include "../wrapper/monitor/GLDebug.hpp"
#include "../global/ChineseOutput.hpp"
#include "../global/EngineDataProperties.h"
#include "../application/app/Application.h"
#include "../glFramework/shader/Shader.h"
#include "../glFramework/constant/engine_layout.h"

#include "../glFramework/bo/VBO.h"
#include "../glFramework/bo/VAO.h"
#include "../glFramework/bo/EBO.h"

#include <memory>


inline const char* vertexPath = "E:\\cpp\\GLRenderEngine\\demo\\shader\\_004\\vertex_shader.glsl";
inline const char* fragmentPath = "E:\\cpp\\GLRenderEngine\\demo\\shader\\_004\\fragment_shader.glsl";

inline std::vector<float> vertices;
inline std::vector<unsigned int> indices;

inline void onResize(int w, int h) {
    glViewport(0, 0, w, h);
    std::cout << "w: " << w << " h: " << h << std::endl;
}

inline void render() {
    ChineseOutput::init();
    EngineApp.initDefaultWindowConfig();
    EngineApp.setResizeCallback(onResize);
    EngineApp.init();

    // data prepare
    vertices.push_back(0.5f);
    vertices.push_back(0.5f);
    vertices.push_back(0.0f);
    vertices.push_back(1.0f);
    vertices.push_back(0.0f);
    vertices.push_back(0.0f);

    vertices.push_back(0.5f);
    vertices.push_back(-0.5f);
    vertices.push_back(0.0f);
    vertices.push_back(0.0f);
    vertices.push_back(1.0f);
    vertices.push_back(0.0f);

    vertices.push_back(-0.5f);
    vertices.push_back(-0.5f);
    vertices.push_back(0.0f);
    vertices.push_back(0.0f);
    vertices.push_back(0.0f);
    vertices.push_back(1.0f);

    vertices.push_back(-0.5f);
    vertices.push_back(0.5f);
    vertices.push_back(0.0f);
    vertices.push_back(1.0f);
    vertices.push_back(0.0f);
    vertices.push_back(0.0f);

    indices.push_back(0);
    indices.push_back(1);
    indices.push_back(2);
    indices.push_back(0);
    indices.push_back(2);
    indices.push_back(3);

    // shader
    std::unique_ptr<Shader> shader = std::make_unique<Shader>(vertexPath, fragmentPath);

    VAO vao;
    VBO vbo(vertices);
    EBO ebo(indices);
    glVertexAttribPointer(shader->getLocation(EngineLocationName::A_POS), 3, GL_FLOAT, GL_FALSE, fSize(6), reinterpret_cast<void *>(0));
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(shader->getLocation(EngineLocationName::A_COLOR), 3, GL_FLOAT, GL_FALSE, fSize(6), reinterpret_cast<void *>(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    vao.unbind();

    std::string uw = "uW";
    std::string uH = "uH";
    std::string uTime = "uTime";

    // render
    while (EngineApp.update()) {
        GL_CALL(glClear(GL_COLOR_BUFFER_BIT))

        shader->bindProgram();

        float time = static_cast<float>(glfwGetTime());

        shader->setUniform(uw, static_cast<float>(EngineApp.getCurrentWindowWidth()));
        shader->setUniform(uH, static_cast<float>(EngineApp.getCurrentWindowHeight()));
        shader->setUniform(uTime, static_cast<float>(glm::sin(glm::radians(10.0 * time))));

        vao.bind();
        GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0))
        vao.unbind();
        shader->unbindProgram();
    }

    shader->deleteProgram();
    vao.destroy();
    EngineApp.destroy();
}
